package com.dm.cloud.service.impl;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.dm.cloud.api.dto.Resources;
import com.dm.cloud.api.service.IResourcesService;
import com.dm.cloud.api.vo.ResourcesVo;
import com.dm.cloud.common.R;
import com.dm.cloud.dao.ResourcesDao;
import com.dm.cloud.utils.DtoPreOpratrionUtils;
import com.dm.cloud.utils.MysqlLogger;
import com.dm.cloud.utils.Oauth2Utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ResourcesServiceImpl implements IResourcesService {

    @Autowired
    private ResourcesDao resourcesDao;

    @Override
    public R createResources(ResourcesVo resourcesVo) {
        Resources resources = new Resources();
        BeanUtils.copyProperties(resourcesVo,resources);

        if(StringUtils.isBlank(resourcesVo.getTitle())){
            return R.failure("菜单名称不能为空！");
        }

        if(null == resourcesVo.getSortNumber()){
            return R.failure("菜单排序顺序不能为空！");
        }

        try{
            //查询菜单是否存在
//            QueryWrapper<Resources> queryWrapper =new QueryWrapper<>();
//            queryWrapper.eq("title", resourcesVo.getTitle());
//            queryWrapper.eq("delete_flag", 0);
//            long accounts = resourcesDao.selectCount(queryWrapper);
//            if(accounts>0){
//                return ResultVo.failure("该菜单名称已存在！");
//            }

            //如果是目录则默认组件名称为 LAYOUT
            if(0 == resources.getType()){
                resources.setUrl("LAYOUT");
            }

            if(ObjectUtils.isNotNull(resources.getIsOut()) && 1 == resources.getIsOut()){
                //外链地址
                resources.setComponentUrl(resources.getUrl());
                resources.setUrl("IFrame");
            }

            //记录注册时间
            new DtoPreOpratrionUtils<Resources>().preInsert(resources);
            resourcesDao.insert(resources);
            MysqlLogger.info(String.format("创建菜单【%s】！", resources.getTitle()));
            return R.success();
        }catch (Exception ex){
            log.error(String.format("创建菜单【%s】失败！", resources.getTitle()));
            return R.failure("系统异常,创建失败！");
        }
    }

    @Override
    @Transactional
    public R updateResources(ResourcesVo resourcesVo) {
        Resources resources = new Resources();
        BeanUtils.copyProperties(resourcesVo,resources);

        //先判断上级部菜单是不是当前菜单的下级菜单  即下级部菜单篡位 先修改下级菜单
        if(StringUtils.isNotBlank(resourcesVo.getParentId())){
            QueryWrapper searcheri = new QueryWrapper();
            searcheri.eq("parent_id",resourcesVo.getId());
            searcheri.eq("id",resourcesVo.getParentId());
            searcheri.eq("delete_flag",0);
            if(resourcesDao.selectCount(searcheri)>0){
                //下级部门篡位
                Resources cuDept = resourcesDao.selectById(resourcesVo.getId());
                String papaId= cuDept.getParentId();
                Resources lowUp = new Resources();
                lowUp.setId(Integer.valueOf(resourcesVo.getParentId()));
                lowUp.setParentId(papaId);
                resourcesDao.updateById(lowUp);
            }
        }

        //如果是目录则默认组件名称为 LAYOUT
        if(null != resources.getType() && 0 == resources.getType()){
            resources.setUrl("LAYOUT");
        }

        if(null != resources.getIsOut() && 1 == resources.getIsOut()){
            //外链地址
            resources.setComponentUrl(resources.getUrl());
            resources.setUrl("IFrame");
        }

        new DtoPreOpratrionUtils<Resources>().preUpdate(resources);
        if(resourcesDao.updateById(resources)>0 && invalidResource(resourcesVo).getCode() == 0){
            MysqlLogger.info(String.format("修改菜单【%s】信息",resources.getTitle()));
            return R.success("修改成功！");
        }else{
            log.error(String.format("修改菜单【%s】信息失败",resources.getTitle()));
            return R.failure("修改失败！");
        }
    }

    @Override
    public R deleteResources(ResourcesVo resourcesVo) {
        List<String> ids = new ArrayList<>();
        getAllResourceNode(ids,resourcesVo.getId().toString());

        if (CollectionUtils.isNotEmpty(ids)) {
            Resources resources = new Resources();
            resources.setDeleteFlag(1);
            new DtoPreOpratrionUtils<Resources>().preInsert(resources);

            UpdateWrapper<Resources> updateWapper =new UpdateWrapper<>();
            updateWapper.in("id",ids);


            if(resourcesDao.update(resources,updateWapper)>0){
                MysqlLogger.info(String.format("删除菜单信息【%s】",resources.getTitle()));
            }else{
                return R.failure("菜单信息删除失败！");
            }
        }
        return R.success("菜单信息删除成功！");
    }

    @Override
    public R checkInvalid(ResourcesVo resourcesVo) {
        List<String> ids = new ArrayList<>();
        QueryWrapper searcher = new QueryWrapper();

        //部门名称不能重复
        if(StringUtils.isNotBlank(resourcesVo.getTitle())){
//            QueryWrapper searcheri = new QueryWrapper();
//            searcheri.eq("title",resourcesVo.getTitle());
//            searcheri.eq("delete_flag",0);
//            searcheri.ne("id",resourcesVo.getId());
//            if(resourcesDao.selectCount(searcheri)>0){
//                return ResultVo.failure("该菜单名称已存在！");
//            }
        }else{
            return R.failure("菜单名称不能为空！");
        }

        //判断节点是不是调整了层级结构 上级部菜单不能是自己或者自己的子部门
        if(StringUtils.isNotBlank(resourcesVo.getParentId())){
            if(resourcesVo.getId().toString().equals(resourcesVo.getParentId())){
                return R.failure("上级菜单不能是当前菜单！");
            }
        }

        if(resourcesVo.getStatus() == 0) {
            //禁用 全部下级节点
            getAllResourceNode(ids, resourcesVo.getId().toString());
            ids.remove(resourcesVo.getId().toString());
            long count = 0 ;
            if(ids.size()>0) {
                //查询这些节点中还有没有启用的
                searcher.eq("status", 1);
                searcher.in("id", ids);

                count = resourcesDao.selectCount(searcher);
            }
            return R.success(count);
        }else{
            //启用 全部上级节点
            getAllParentNode(ids, resourcesVo.getId().toString());
            ids.remove(resourcesVo.getId().toString());
            long count = 0 ;
            if(ids.size()>0) {
                //查询这些节点中还有没有停用的
                searcher.eq("status",0);
                searcher.in("id",ids);
                count = resourcesDao.selectCount(searcher);
            }
            return R.success(count);
        }
    }

    @Override
    public R invalidResource(ResourcesVo resourcesVo) {
        String authorization = Oauth2Utils.getAuthorization();
        UserDetails user = Oauth2Utils.getByAuthorization(authorization);

        List<String> ids = new ArrayList<>();

        if(resourcesVo.getStatus() == 0) {

            getAllResourceNode(ids, resourcesVo.getId().toString());

            if (CollectionUtils.isNotEmpty(ids)) {
                //停用将停用其所有子部门
                try{
                    resourcesDao.invalidByIds(ids, user.getUsername(),0);
                    MysqlLogger.info(String.format("停用资源【%s】", resourcesVo.getTitle()));
                }catch (Exception ex){
                    return R.failure("停用状态修改失败！");
                }
            }
            return R.success("停用状态修改成功！");
        }else{
            //启用 将启用全部上级节点
            getAllParentNode(ids, resourcesVo.getId().toString());

            if (CollectionUtils.isNotEmpty(ids)) {
                //启用将启用其所有上级部门
                try{
                    resourcesDao.invalidByIds(ids, user.getUsername(),1);
                    MysqlLogger.info(String.format("启用资源【%s】",resourcesVo.getTitle()));
                }catch (Exception ex){
                    return R.failure("启用状态修改失败！");
                }
            }
            return R.success("启用状态修改成功！");
        }
    }

    @Override
    public R selectPage(ResourcesVo resourcesVo) {
        ResourcesVo resultContainer = new ResourcesVo();
        resultContainer.setSortType("layout");

        QueryWrapper<Resources> usersQueryWrapper = new QueryWrapper<>();
        usersQueryWrapper.eq("delete_flag",0);
        usersQueryWrapper.orderByDesc("update_date");
        List<Resources> list = resourcesDao.selectList(usersQueryWrapper);

        //名称单独筛选，要把当前名称的筛选出来 还要把上级带出来
        if(CollectionUtils.isNotEmpty(list)){
            List<String> ids = new ArrayList<>();

            //找到实际有用的部门信息
            List<String> likesidList = new ArrayList<>();

            //名称相似的部门ID
            likesidList = list.stream()
                    .filter(e ->{
                        if(StringUtils.isNotBlank(resourcesVo.getTitle()) && !e.getTitle().contains(resourcesVo.getTitle())){
                            return false;
                        }
                        if(null != resourcesVo.getStatus() && e.getStatus() != resourcesVo.getStatus()){
                            return false;
                        }
                        return true;
                    })
                    .map(e -> e.getId().toString()).collect(Collectors.toList());

            //找到上述部门的所有上级 注意处理重复
            getAllParentNode(ids, likesidList.toArray(new String[0]));
            ids = ids.stream().distinct().collect(Collectors.toList());

            //然后将id在ids内的部门按照关系整理好
            List<String> finalIds = ids;
            list = list.stream().filter(e -> finalIds.contains(e.getId().toString())).collect(Collectors.toList());


            setChildTree(resultContainer,list);
        }

        return R.success(resultContainer.getChildren());
    }

    @Override
    public R searchResource(String id) {
        Resources record = resourcesDao.selectById(id);
        ResourcesVo result =new ResourcesVo();
        BeanUtils.copyProperties(record,result);
        return R.success(result);
    }

    /**
     * 获取指定部门下的所有资源
     * @param ids
     * @param id
     */
    private void getAllResourceNode(List<String> ids, String... id){

        List<String> idCurrent = Arrays.asList(id);
        ids.addAll(idCurrent);

        //查询有没有子节点
        UpdateWrapper<Resources> childUpdateWapper =new UpdateWrapper<>();
        childUpdateWapper.in("parent_id",idCurrent);
        List<Resources> childNode = resourcesDao.selectList(childUpdateWapper);

        if(CollectionUtils.isNotEmpty(childNode))
        {
            List<String> idsinner = childNode.stream().map(e->e.getId().toString()).collect(Collectors.toList());
            String[] idsArr = idsinner.toArray(new String[0]);
            getAllResourceNode(ids, idsArr);
        }
    }

    /**
     * 获取指定资源下的所有上级 包括自己
     * @param ids
     * @param id
     */
    private void getAllParentNode(List<String> ids, String... id){

        if(null == id) {
            return;
        }

        ids.addAll(Arrays.asList(id));

        //查询当前部门
        UpdateWrapper<Resources> childUpdateWapper =new UpdateWrapper<>();
        childUpdateWapper.in("id",id);
        List<Resources> current = resourcesDao.selectList(childUpdateWapper);

        if(CollectionUtils.isNotEmpty(current))
        {
            List<String> idsinner = current.stream().map(e->e.getParentId()).collect(Collectors.toList());
            String[] idsArr = idsinner.toArray(new String[0]);
            getAllParentNode(ids, idsArr);
        }
    }

    /**
     * 整理菜单树信息
     * @param result
     * @param depts
     */
    private void setChildTree(ResourcesVo result, List<Resources> resources){

        if(result == null || CollectionUtils.isEmpty(result.getChildren())){
            //先初始化 在循环
            String currentId = "" ;

            //判断是不是根节点
            if(!"layout".equals(result.getSortType())){
                currentId = result.getId().toString();
            }

            String finalCurrentId = currentId;
            result.setChildren(resources.stream()
                    .map(e->{
                        if(StringUtils.isBlank(e.getParentId())){
                            e.setParentId("");
                        }
                        return e;
                    }).filter(e-> finalCurrentId.equals(e.getParentId()))
                    .map(e->{
                        ResourcesVo resourcesVo = new ResourcesVo();
                        BeanUtils.copyProperties(e,resourcesVo);
                        return resourcesVo;
                    }).sorted(new Comparator<ResourcesVo>() {
                        @Override
                        public int compare(ResourcesVo o1, ResourcesVo o2) {
                            return o1.getSortNumber().compareTo(o2.getSortNumber());
                        }
                    }).collect(Collectors.toList()));

            if(CollectionUtils.isEmpty(result.getChildren())){
                return;
            }
            setChildTree(result,resources);
        }else{
            for (ResourcesVo departmentVo : result.getChildren()) {
                setChildTree(departmentVo,resources);
            }
        }
    }

}
